<template>
  <div id="app">
    <div
      class="parentBox"
      ref="parent"
      :style="[
        {
          borderWidth: `${tool.parentBorderSize}px`,
        },
      ]"
    >
      <div
        class="childrenBox"
        ref="children"
        @mousemove="childrenBoxMouseMove"
        :style="[
          childrenBox.style[childrenBox.state],
          {
            width: `${childrenBox.width}px`,
            height: `${childrenBox.height}px`,
            left: `${childrenBox.positionLeft}px`,
            top: `${childrenBox.positionTop}px`,
            borderWidth: `${tool.childrenBorderSize}px`,
          },
        ]"
      ></div>
    </div>
    <section>
      <div class="set">
        <el-popover placement="bottom-end" width="300" trigger="hover">
          <template>
            <div class="setBody w100">
              <el-descriptions
                title="设置属性"
                :column="1"
                :labelStyle="{ width: '120px' }"
                :contentStyle="{ padding: '20px' }"
                border
                size="mini"
              >
                <el-descriptions-item>
                  <template slot="label">
                    <div class="decStyle">关闭console</div>
                  </template>
                  <div>
                    <el-switch
                      v-model="tool.console"
                      active-color="#13ce66"
                      inactive-color="#ff4949"
                    >
                    </el-switch>
                  </div>
                </el-descriptions-item>
                <el-descriptions-item>
                  <template slot="label">
                    <div class="decStyle">父元素边框尺寸</div>
                  </template>
                  <div>
                    <el-slider
                      :max="5"
                      :min="1"
                      class="w100"
                      v-model="tool.parentBorderSize"
                      :step="1"
                      show-stops
                    >
                    </el-slider>
                  </div>
                </el-descriptions-item>
                <el-descriptions-item>
                  <template slot="label">
                    <div class="decStyle">子元素边框尺寸</div>
                  </template>
                  <div>
                    <el-slider
                      :max="5"
                      :min="1"
                      class="w100"
                      v-model="tool.childrenBorderSize"
                      :step="1"
                      show-stops
                    >
                    </el-slider>
                  </div>
                </el-descriptions-item>
                <el-descriptions-item>
                  <template slot="label">
                    <div class="decStyle">父元素吸附距离</div>
                  </template>
                  <div>
                    <el-slider
                      :max="200"
                      :min="30"
                      class="w100"
                      v-model="tool.adsorb"
                      :step="10"
                      show-stops
                    >
                    </el-slider>
                  </div>
                </el-descriptions-item>
                <el-descriptions-item>
                  <template slot="label">
                    <div class="decStyle">子元素触发距离</div>
                  </template>
                  <div>
                    <el-slider
                      :max="10"
                      :min="5"
                      class="w100"
                      v-model="tool.threshold"
                      :step="1"
                      show-stops
                    >
                    </el-slider>
                  </div>
                </el-descriptions-item>
              </el-descriptions>
            </div>
          </template>
          <el-button slot="reference" type="primary" icon="el-icon-s-tools" circle></el-button>
        </el-popover>
      </div>
    </section>
    <!-- 调试器 -->
    <transition name="el-fade-in-linear">
      <section class="console" v-show="tool.console">
        <div>全局内部坐标X:{{ window.position.x }}</div>
        <div>全局内部坐标Y:{{ window.position.y }}</div>
        <div class="cut"></div>
        <div>子盒子宽度:{{ childrenBox.width }}</div>
        <div>子盒子高度:{{ childrenBox.height }}</div>
        <div>子盒子左偏移:{{ childrenBox.positionLeft }}</div>
        <div>子盒子上偏移:{{ childrenBox.positionTop }}</div>
        <div>子盒子内部坐标X:{{ console.childrenBoxBodyX }}</div>
        <div>子盒子内部坐标Y:{{ console.childrenBoxBodyY }}</div>
        <div>子盒子操作状态:{{ console.childrenState }}</div>
        <div class="cut"></div>
        <div>子盒左空间:{{ console.marginLeft }}</div>
        <div>子盒右空间:{{ console.marginRight }}</div>
        <div>子盒上空间:{{ console.marginTop }}</div>
        <div>子盒下空间:{{ console.marginBottom }}</div>
      </section>
    </transition>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
  data() {
    return {
      window: {
        position: {},
      },
      parentBox: {
        margin: null,
        target: null,
        mouseDown: false,
        mouseDownPosition: {},
        spedMovePosition: {},
        movePosition: {},
      },
      childrenBox: {
        margin: null,
        width: 200,
        height: 200,
        positionLeft: 0,
        positionTop: 0,
        state: "none",
        target: null,
        style: {
          left: { borderLeftColor: "green" },
          right: { borderRightColor: "green" },
          top: { borderTopColor: "green" },
          bottom: { borderBottomColor: "green" },
          warn: {},
        },
      },
      ban: {
        left: false,
        right: false,
        top: false,
        bottom: false,
      },
      console: {
        parentBoxBodyX: 0,
        parentBoxBodyY: 0,
        childrenBoxBodyX: 0,
        childrenBoxBodyY: 0,
        childrenState: "无操作",
        marginLeft: 0,
        marginRight: 0,
        marginTop: 0,
        marginBottom: 0,
      },
      tool: {
        console: true,
        parentBorderSize: 3,
        childrenBorderSize: 2,
        adsorb: 90,
        threshold: 5,
        cursor: "",
      },
    };
  },
  mounted() {
    this.childrenBox.target = this.$refs.children;
    this.parentBox.target = this.$refs.parent;
    this.countMargin(true);
    window.addEventListener("mousemove", this.windowMouseMove);
    window.addEventListener("mousedown", this.windowMouseDown);
    window.addEventListener("mouseup", this.windowMouseUp);
  },
  watch: {
    "childrenBox.state"(newVal) {
      switch (newVal) {
        case "left":
          this.console.childrenState = "操作左边";
          document.querySelector("body").style.cursor = "e-resize";
          break;
        case "right":
          this.console.childrenState = "操作右边";
          document.querySelector("body").style.cursor = "e-resize";
          break;
        case "top":
          this.console.childrenState = "操作上边";
          document.querySelector("body").style.cursor = "n-resize";
          break;
        case "bottom":
          this.console.childrenState = "操作下边";
          document.querySelector("body").style.cursor = "n-resize";
          break;
        default:
          this.console.childrenState = "无操作";
          document.querySelector("body").style.cursor = "pointer";
      }
    },
    "console.marginLeft"(newVal) {
      if (newVal <= 0) {
        this.childrenBox.style.left.borderLeftColor = "red";
      } else {
        this.childrenBox.style.left.borderLeftColor = "green";
      }
    },
    "console.marginRight"(newVal) {
      if (newVal <= 0) {
        this.childrenBox.style.right.borderRightColor = "red";
      } else {
        this.childrenBox.style.right.borderRightColor = "green";
      }
    },
    "console.marginTop"(newVal) {
      if (newVal <= 0) {
        this.childrenBox.style.top.borderTopColor = "red";
      } else {
        this.childrenBox.style.top.borderTopColor = "green";
      }
    },
    "console.marginBottom"(newVal) {
      if (newVal <= 0) {
        this.childrenBox.style.bottom.borderBottomColor = "red";
      } else {
        this.childrenBox.style.bottom.borderBottomColor = "green";
      }
    },
  },
  methods: {
    windowMouseDown(e) {
      this.parentBox.mouseDownPosition = {
        x: e.clientX,
        y: e.clientY,
      };

      let state = this.childrenBox.state;
      if (state == "left" || state == "right" || state == "top" || state == "bottom") {
        this.parentBox.mouseDown = true;
      }
    },
    windowMouseUp() {
      this.parentBox.mouseDown = false;
      this.parentBox.movePosition.x = 0;
      this.parentBox.movePosition.y = 0;
      this.childrenBox.state = "none";
    },
    windowMouseMove(e) {
      let position = {};
      position.x = e.clientX;
      position.y = e.clientY;
      this.window.position = position;
      if (this.parentBox.mouseDown) {
        let movePosition = {};
        let spedMovePosition = {};
        //   // 总进
        movePosition.x = this.parentBox.mouseDownPosition.x - e.clientX;
        movePosition.y = this.parentBox.mouseDownPosition.y - e.clientY;
        //   // 步进
        spedMovePosition.x = movePosition.x - (this.parentBox.movePosition.x || 0);
        spedMovePosition.y = movePosition.y - (this.parentBox.movePosition.y || 0);
        // 步进赋值
        this.parentBox.spedMovePosition = spedMovePosition;
        // 总进赋值
        this.parentBox.movePosition = movePosition;
        // 预计算剩余空间
        this.countMargin();
        // 计算禁用情况
        this.judgeBan();
        // 计算宽度和偏移
        this.countSize();
      }
    },
    judgeBan() {
      let step;
      let newVal;
      switch (this.childrenBox.state) {
        case "left":
          step = this.parentBox.spedMovePosition.x;
          newVal = this.console.marginLeft - Math.abs(step);
          if (newVal <= this.tool.adsorb && step > 0) {
            this.ban.left = true;
            this.setLeft(this.console.marginLeft);
          } else if (step < 0) {
            this.ban.left = false;
          }
          break;
        case "right":
          step = this.parentBox.spedMovePosition.x;
          newVal = this.console.marginRight - Math.abs(step);
          if (newVal <= this.tool.adsorb && step < 0) {
            this.ban.right = true;
            this.setRight(-this.console.marginRight);
          } else if (step > 0) {
            this.ban.right = false;
          }
          break;
        case "top":
          step = this.parentBox.spedMovePosition.y;
          newVal = this.console.marginTop - Math.abs(step);
          if (newVal <= this.tool.adsorb && step > 0) {
            this.ban.top = true;
            this.setTop(this.console.marginTop);
          } else if (step < 0) {
            this.ban.top = false;
          }
          break;
        case "bottom":
          step = this.parentBox.spedMovePosition.y;
          newVal = this.console.marginBottom - Math.abs(step);
          if (newVal <= this.tool.adsorb && step < 0) {
            this.ban.bottom = true;
            this.setBottom(-this.console.marginBottom);
          } else if (step > 0) {
            this.ban.bottom = false;
          }
          break;
      }
    },
    // 计算偏移和宽度
    countSize() {
      switch (this.childrenBox.state) {
        case "left":
          if (this.ban.left) return;
          this.setLeft(this.parentBox.spedMovePosition.x);
          break;
        case "right":
          if (this.ban.right) return;
          this.setRight(this.parentBox.spedMovePosition.x);
          break;
        case "top":
          if (this.ban.top) return;
          this.setTop(this.parentBox.spedMovePosition.y);
          break;
        case "bottom":
          if (this.ban.bottom) return;
          this.setBottom(this.parentBox.spedMovePosition.y);
          break;
      }
    },
    setLeft(step) {
      this.childrenBox.width += step;
      this.childrenBox.positionLeft -= step / 2;
    },
    setRight(step) {
      this.childrenBox.width -= step;
      this.childrenBox.positionLeft -= step / 2;
    },
    setTop(step) {
      this.childrenBox.height += step;
      this.childrenBox.positionTop -= step / 2;
    },
    setBottom(step) {
      this.childrenBox.height -= step;
      this.childrenBox.positionTop -= step / 2;
    },
    countMargin(init) {
      // 子盒子边距
      let children = this.childrenBox.target;
      let childrenMargin = {};
      childrenMargin.left = children.offsetLeft;
      childrenMargin.right =
        window.innerWidth - children.offsetLeft - children.offsetWidth;
      childrenMargin.top = children.offsetTop;
      childrenMargin.bottom =
        window.innerHeight - children.offsetTop - children.offsetHeight;
      this.childrenBox.margin = childrenMargin;

      // 父盒子边距
      let parent = this.parentBox.target;
      let parentMargin = {};
      parentMargin.left = parent.offsetLeft;
      parentMargin.right = window.innerWidth - parent.offsetLeft - parent.offsetWidth;
      parentMargin.top = parent.offsetTop;
      parentMargin.bottom = window.innerHeight - parent.offsetTop - parent.offsetHeight;
      this.parentBox.margin = parentMargin;

      switch (this.childrenBox.state) {
        case "left":
          this.console.marginLeft = childrenMargin.left - parentMargin.left;
          break;
        case "right":
          this.console.marginRight = childrenMargin.right - parentMargin.right;
          break;
        case "top":
          this.console.marginTop = childrenMargin.top - parentMargin.top;
          break;
        case "bottom":
          this.console.marginBottom = childrenMargin.bottom - parentMargin.bottom;
          break;
      }
      if (init) {
        this.console.marginLeft = childrenMargin.left - parentMargin.left;
        this.console.marginRight = childrenMargin.right - parentMargin.right;
        this.console.marginTop = childrenMargin.top - parentMargin.top;
        this.console.marginBottom = childrenMargin.bottom - parentMargin.bottom;
      }
    },
    childrenBoxMouseMove(e) {
      // this.childrenBox.width = e.target.clientWidth;
      // this.childrenBox.height = e.target.clientHeight;

      this.console.childrenBoxBodyX = e.layerX;
      this.console.childrenBoxBodyY = e.layerY;
      this.judgeChildrenState();
    },
    judgeChildrenState() {
      let width = this.childrenBox.width;
      let height = this.childrenBox.height;
      let x = this.console.childrenBoxBodyX;
      let y = this.console.childrenBoxBodyY;
      let threshold = this.tool.threshold;

      if (this.parentBox.mouseDown == true) {
        return;
      }
      let xnone = false;
      let ynone = false;
      console.log(x);
      if (x <= threshold && x > 0) {
        this.childrenBox.state = "left";
      } else if (width - x <= threshold && width - x >= 0) {
        this.childrenBox.state = "right";
      } else {
        xnone = true;
      }
      if (y <= 20 && x > 0) {
        this.childrenBox.state = "top";
      } else if (height - y <= threshold && height - y >= 0) {
        this.childrenBox.state = "bottom";
      } else {
        ynone = true;
      }
      if (xnone && ynone) {
        this.childrenBox.state = "none";
      }
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  /* background: #ccc; */
}

.parentBox {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 700px;
  height: 700px;
  border: solid #999;
  margin: 0 auto;
}

.childrenBox {
  position: relative;
  border: solid #ccc;
}

.console {
  position: fixed;
  left: 50px;
  top: 50px;
  width: 250px;
  height: 500px;
  background: #080808;
  color: rgba(78, 235, 16, 0.829);
  text-align: left;
  padding: 5px;
  overflow-y: auto;
  user-select: none;
}

.cut {
  width: 100%;
  height: 1px;
  background: rgba(78, 235, 16, 0.829);
  margin: 10px 0;
}
.set {
  position: fixed;
  right: 50px;
  top: 50px;
}
.w100 {
  width: 100%;
}
</style>
